<template>
    <div class="app" style="height: 100vh">
        <vue-flow-editor
                ref="editor"
                :data="state.data"
                :grid="showGrid"
                :miniMap="showMiniMap"
                :onRef="onRef"
                :multipleSelect="true"
                :loading="state.editorLoading"
                editorTitle=" "

                :beforeDelete="handleBeforeDelete"
                :afterDelete="handleAfterDelete"
                :beforeAdd="handleBeforeAdd"
                :afterAdd="handleAfterAdd"

                @dblclick-node="onDblclickNode"
                @dblclick-edge="onDblClickEdge"

                :activityConfig="state.activityConfig"
        >
            <div slot="menu">
                <vue-flow-edit-menu-group label="活动节点" value>
                    <vue-flow-edit-menu v-for="(value,key) in state.activityConfig" :key="key" :model="{activity:key,text:value.text,desc:value.desc}">
                        <template slot="content">
                            <div class="activity-menu">
                                <img :src="value.img">
                                <span>{{value.text}}</span>
                            </div>
                        </template>
                    </vue-flow-edit-menu>
                </vue-flow-edit-menu-group>
                <vue-flow-edit-menu-group v-for="(group,groupIndex) in state.menuData" :label="group.label" :key="groupIndex" value>
                    <vue-flow-edit-menu v-for="(menu,menuIndex) in group.menus" :key="menuIndex" :model="menu"/>
                </vue-flow-edit-menu-group>
            </div>
            <div slot="model" style="padding: 16px">
                <el-form v-if="!!state.detailModel" ref="form" :model="state.detailModel" label-width="100px">

                    <template v-if="state.detailModel.activity === undefined">
                        <el-form-item label="节点名称" prop="label">
                            <el-input v-model="state.detailModel.label"/>
                        </el-form-item>

                        <template v-if="state.detailModel.type !== 'edge'">
                            <el-form-item label="节点背景色" prop="style.fill">
                                <el-color-picker v-model="state.detailModel.style.fill"/>
                            </el-form-item>
                            <el-form-item label="节点边框色" prop="style.stroke">
                                <el-color-picker v-model="state.detailModel.style.stroke"/>
                            </el-form-item>
                            <el-form-item label="节点文字色" prop="labelCfg.style.stroke">
                                <el-color-picker v-model="state.detailModel.labelCfg.style.fill"/>
                            </el-form-item>
                        </template>
                    </template>
                    <template v-else>
                        <el-form-item label="活动标题">
                            <el-input v-model="state.detailModel.text"/>
                        </el-form-item>
                        <el-form-item label="活动副标题">
                            <el-input v-model="state.detailModel.desc"/>
                        </el-form-item>
                        <el-form-item label="活动类型">
                            <el-select v-model="state.detailModel.activity">
                                <el-option
                                        v-for="(value,key) in state.activityConfig"
                                        :key="key"
                                        :label="value.text"
                                        :value="key"/>
                            </el-select>
                        </el-form-item>
                    </template>

                </el-form>
            </div>

            <template slot="toolbar">
                <el-tooltip content="测试工具栏插槽">
                    <div class="vue-flow-editor-toolbar-item" @click="logData">
                        <i class="el-icon-search"/>
                    </div>
                </el-tooltip>
            </template>

            <template slot="foot">
                <el-button type="primary" @click="save">保存</el-button>
                <el-button @click="cancel">取消</el-button>
            </template>
        </vue-flow-editor>
    </div>
</template>

<script lang="ts">
    import {reactive} from '@vue/composition-api'
    import {AppData} from "./data.js";
    import {staticPath} from "./utils";

    /*const AppData = {
        // 点集
        nodes: [
            {
                id: 'node1', // String，该节点存在则必须，节点的唯一标识
                shape: 'activity',
                img: '/images/start-node.png',
                text: '砸金蛋',
                desc: '砸金蛋抽奖活动',
                color: '',
                x: 200, // Number，可选，节点位置的 x 值
                y: 100, // Number，可选，节点位置的 y 值
            },
            {
                id: 'node2', // String，该节点存在则必须，节点的唯一标识
                shape: 'activity',
                img: '/images/end-node.png',
                text: '滚动抽奖',
                desc: '在大屏幕上滚动抽奖',
                x: 500, // Number，可选，节点位置的 x 值
                y: 300, // Number，可选，节点位置的 y 值
            },
            {
                id: 'node3', // String，该节点存在则必须，节点的唯一标识
                shape: 'image',
                img: '/vue.png',
                size: [50, 50],
                x: 400, // Number，可选，节点位置的 x 值
                y: 200, // Number，可选，节点位置的 y 值
            },
        ],
        // 边集
        edges: [
            {
                source: 'node1', // String，必须，起始点 id
                target: 'node2', // String，必须，目标点 id
            },
        ],
    }*/

    const Ele = (window as any).ELEMENT

    const G6 = (window as any).G6.default as any

    function delay(time) {
        return new Promise((resolve) => setTimeout(resolve, time))
    }

    export default {
        name: "App.vue",
        setup(props, context) {

            const state = reactive({
                data: AppData,
                detailModel: null,
                editorLoading: false,

                selectOptions: [
                    {label: '待确认', value: '0'},
                    {label: '填写表单', value: '1'},
                    {label: '部门负责人审批', value: '2'},
                    {label: '总经理审批', value: '3'},
                ],
                menuData: [
                    {
                        label: '流程节点',
                        menus: [
                            {label: '开始', shape: 'ellipse', id: 'start-node'},
                            {label: '结束', shape: 'ellipse', id: 'end-node'},
                            {label: '审批节点', busType: '123'},
                            {label: '判断节点', shape: 'diamond',},
                        ],
                    },
                    {
                        label: '其他形状节点',
                        menus: [
                            {label: '矩形节点', shape: 'rect'},
                            {label: '圆形节点', shape: 'circle'},
                            {label: '椭圆节点', shape: 'ellipse'},
                            {label: '菱形节点', shape: 'diamond'},
                            {label: '三角形节点', shape: 'triangle'},
                            {label: '星形节点', shape: 'star'},
                        ]
                    }
                ],
                activityConfig: {
                    advertisement: {
                        text: '广告宣传',
                        desc: '通过广告宣传新品',
                        color: '#9283ed',
                        img: staticPath('/images/activity/advertisement-node.svg'),
                    },
                    coupon: {
                        text: '优惠券',
                        desc: '发放奖励优惠券',
                        color: '#ed8383',
                        img: staticPath('/images/activity/coupon-node.svg'),
                    },
                    crowd: {
                        text: '用户反馈',
                        desc: '收集用户反馈信息',
                        color: '#92dba8',
                        img: staticPath('/images/activity/crowd-node.svg'),
                    },
                }
            })

            let editor;

            function onDblclickNode(e) {

                const model = G6.Util.clone(e.item.get('model'))
                model.style = model.style || {}
                model.labelCfg = model.labelCfg || {style: {}}

                state.detailModel = model
                editor.openModel()
            }

            function onDblClickEdge(e) {
                const {source, target, style, labelCfg, label} = e.item.get('model')
                const model = {label, source, target, style: style || {}, labelCfg: labelCfg || {style: {}}, type: null, id: null}
                model.type = e.item.get('type')
                model.id = e.item.get('id')

                state.detailModel = model
                editor.openModel()
            }

            function cancel() {
                editor.closeModel()
            }

            function save() {
                editor.updateModel(state.detailModel)
                editor.closeModel()
            }

            async function handleBeforeDelete(model, type) {
                if (type === 'node') {
                    if (model.label === '开始') {
                        state.editorLoading = true
                        await delay(1000)
                        state.editorLoading = false
                        Ele.Notification.error('不可以删除【开始】节点')
                        return Promise.reject('reject')
                    }
                }
            }

            function handleAfterDelete(model, type) {
                if (type === 'edge') {
                    console.log('delete edge')
                } else {
                    console.log('after delete', model.label, {...model})
                }
            }

            function handleBeforeAdd(model, type) {
                if (type === 'edge') {
                    if (model.source === 'end-node') {
                        Ele.Notification.error('结束节点不能输出连线其他节点')
                        return Promise.reject('reject')
                    }
                }
                if (type === 'node') {
                    if (model.id === 'start-node' || model.id === 'end-node') {
                        const data = editor.editorState.graph.save()
                        for (let i = 0; i < data.nodes.length; i++) {
                            const node = data.nodes[i];
                            if (node.id === model.id) {
                                Ele.Notification.error(`只能有一个${model.id === 'start-node' ? '开始' : '结束'}节点`)
                                return Promise.reject('reject')
                            }
                        }
                    }
                }
            }

            function handleAfterAdd(model, type) {
                if (type === 'edge') {
                    console.log(`新增连接线`)
                }
            }

            function logData() {
                let {nodes, edges} = editor.editorState.graph.save()
                nodes = nodes.map(({data, id, label, shape, x, y, text, desc, img}) => ({data, id, label, shape, x, y, text, desc, img}))
                edges = edges.map(({source, sourceAnchor, target, targetAnchor}) => ({source, sourceAnchor, target, targetAnchor}))
                console.log(JSON.stringify({nodes, edges}, null, 2))
            }

            return {
                state,

                showGrid: true,
                showMiniMap: false,

                onDblclickNode,
                onDblClickEdge,
                cancel,
                save,
                handleBeforeDelete,
                handleAfterDelete,
                handleBeforeAdd,
                handleAfterAdd,

                logData,

                onRef: e => editor = e,
                staticPath,
            }
        },
    }
</script>

<style lang="scss">
    html, body {
        padding: 0;
        margin: 0;

        .activity-menu {
            display: flex;
            align-items: center;

            img {
                margin-right: 1em;
                width: 30px;
                height: 30px;
            }
        }
    }
</style>